﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Shapes.Geometry;
using Shapes.Misc.Appearance;
using Shapes.Misc;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace ShapesExtensions
{
    /// <summary>
    /// A GeometrySprite is a class which holds a Shape and a Texture generated from the shape.
    /// </summary>
    public class GeometrySprite : IDisposable, ITransformable2D
    {
        /// <summary>
        /// The Geometry which has been used to create the texture
        /// </summary>
        public Drawing Geometry { get; private set; }

        public Vector2 Position { get { return Geometry.Position; } set { Geometry.Position = value; } }

        public Vector2 Origin { get { return Geometry.Origin; } set { Geometry.Origin = value; } }

        public Vector2 Scale { get { return Geometry.Scale; } set { Geometry.Scale = value; } }

        public Angle Rotation { get { return Geometry.Rotation; } set { Geometry.Rotation = value; } }

        Brush _Brush;

        /// <summary>
        /// The texture showing the geometry
        /// </summary>
        public Texture2D Texture { get; private set; }
        /// <summary>
        /// Gets or sets the color of the texture (not the fill- or brush color of the geometry)
        /// </summary>
        public Color Color { get { return _Color; } set { _Color = value; } }
        Color _Color = Color.White;

        /// <summary>
        /// Gets or sets the layer depth.
        /// </summary>
        public float LayerDepth { get { return _LayerDepth; } set { _LayerDepth = value; } }
        float _LayerDepth = 0.5f;

        /// <summary>
        /// Indicates wether the Sprite is drawn or not
        /// </summary>
        public bool IsVisible { get { return _IsVisible; } set { _IsVisible = value; } }
        bool _IsVisible = true;

        /// <summary>
        /// Initializes a new instance of the <see cref="GeometrySprite"/> class.
        /// </summary>
        /// <param name="geometry">The geometry.</param>
        /// <param name="generator">The texture generator.</param>
        public GeometrySprite(Shape geometry, TextureGenerator generator)
        {
            Geometry = geometry;
            Texture = generator.GeometryFilled(geometry);
            _Brush = null;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GeometrySprite"/> class.
        /// </summary>
        /// <param name="geometry">The geometry.</param>
        /// <param name="generator">The texture generator.</param>
        /// <param name="brush">The brush.</param>
        public GeometrySprite(Drawing geometry, TextureGenerator generator, Brush brush)
        {
            Geometry = geometry;
            Texture = generator.GeometryBorder(geometry, brush);
            _Brush = brush;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GeometrySprite"/> class.
        /// </summary>
        /// <param name="geometry">The geometry.</param>
        /// <param name="generator">The texture generator.</param>
        /// <param name="color">The color.</param>
        public GeometrySprite(Shape geometry, TextureGenerator generator, Fill fill)
        {
            Geometry = geometry;
            Texture = generator.GeometryFilled(geometry, fill);
            _Brush = null;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="GeometrySprite"/> class.
        /// </summary>
        /// <param name="geometry">The geometry.</param>
        /// <param name="generator">The texture generator.</param>
        /// <param name="color">The color.</param>
        /// <param name="brush">The brush.</param>
        public GeometrySprite(Shape geometry, TextureGenerator generator, Fill fill, Brush brush)
        {
            Geometry = geometry;
            Texture = generator.GeometryFilledWithBorder(geometry, fill, brush);
            _Brush = brush;
        }


        /// <summary>
        /// Draws the geometry.
        /// </summary>
        /// <param name="batch">The sprite batch to draw with.</param>
        public void Draw(SpriteBatch batch)
        {
            if (!_IsVisible)
                return;
            
            Vector2 offset = Vector2.Zero;
            if (_Brush != null)
                offset = _Brush.GetTextureOffset();

            batch.Draw(Texture, Geometry.Transform.Position, null, _Color, Geometry.Transform.Rotation.ClockwiseRadians,
                Geometry.Transform.Origin + offset, Geometry.Transform.Scale, SpriteEffects.None, _LayerDepth);
        }

        #region IDisposable Member

        public void Dispose()
        {
            this._Brush = null;
            
            this.Geometry.Dispose();
            this.Geometry = null;

            this.Texture.Dispose();
            this.Texture = null;
        }

        #endregion
    }
}
